//
//  AlbumsManager.m
//  DAlbum
//
//  Created by David Qiu on 15/9/7.
//  Copyright (C) 2015, David Qiu. All rights reserved.
//

#import "AlbumsManager.h"



/**
 *  Albums manager. (Internal Interface)
 */
@interface AlbumsManager ()

/**
 *  Path of the albums directory.
 */
@property NSString* albumsDirectoryPath;

/**
 *  List
 */
@property NSArray* albumsList;
@property NSArray* picturesList;

@end


@implementation AlbumsManager

#pragma mark - Object Control

+ (instancetype) defaultManager {
    static AlbumsManager* _defaultManager = nil;
    
    // Initialize the default manager [once]
    static dispatch_once_t onceTokenForDefaultManagerInit;
    dispatch_once(&onceTokenForDefaultManagerInit, ^{
        _defaultManager = [[AlbumsManager alloc] init];
    });
    
    // Return the default manager
    return _defaultManager;
}

- (id) init {
    if (self = [super init]) {
        // Initialize the albums directory path
        NSString* documentDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        self.albumsDirectoryPath = [documentDirectoryPath stringByAppendingPathComponent:@"Albums"];
        NSLog(@"[ INFO ] Initialize the albums directory path. (path: \"%@\")", self.albumsDirectoryPath);
    }
    
    return self;
}


#pragma mark - Internal Methods

- (void) refreshAlbumsList {
    NSMutableArray* arrAlbums = [[NSMutableArray alloc] init];
    
    // Enumerate the albums directory
    NSDirectoryEnumerator* enumeratorAlbumsDirectory = [[NSFileManager defaultManager] enumeratorAtPath:self.albumsDirectoryPath];
    NSString* item;
    while (item = [enumeratorAlbumsDirectory nextObject]) {
        // Construct the full path of the item
        NSString* itemPath = [self.albumsDirectoryPath stringByAppendingPathComponent:item];
        
        // Check if the current item is a directory
        BOOL isDirectory;
        [[NSFileManager defaultManager] fileExistsAtPath:itemPath isDirectory:&isDirectory];
        if (isDirectory) {
            [arrAlbums addObject:item];
        }
    }
    
    // Construct the albums list
    self.albumsList = [arrAlbums copy];
}

- (void) checkThumbnailByPath:(NSString *)path {
#warning TODO: Check existence and if the the corresponding picture exists
}

- (void) refreshPicturesList {
    NSMutableArray* arrPictures = [[NSMutableArray alloc] init];
    
    // Refresh the albums list
    [self refreshAlbumsList];
    
    // Check if the current selected album exists
    BOOL doAlbumExists = NO;
    if (self.selectedAlbumName) {
        for (NSUInteger i=0; i<self.albumsList.count; ++i) {
            if ([((NSString *)[self.albumsList objectAtIndex:i]) isEqual:self.selectedAlbumName]) {
                doAlbumExists = YES;
                break;
            }
        }
    }
    if (!doAlbumExists) {
        self.picturesList = nil;
        return;
    }
    
    // Enumerate the pictures directory
    NSString* picturesDirectoryPath = [self.albumsDirectoryPath stringByAppendingPathComponent:self.selectedAlbumName];
    NSDirectoryEnumerator* enumeratorPicturesDirectory = [[NSFileManager defaultManager] enumeratorAtPath:picturesDirectoryPath];
    NSString* item;
    while (item = [enumeratorPicturesDirectory nextObject]) {
        // Construct the full path of the item
        NSString* itemPath = [picturesDirectoryPath stringByAppendingPathComponent:item];
        
        // Check if the current item is a file
        BOOL isDirectory;
        if (![[NSFileManager defaultManager] fileExistsAtPath:itemPath isDirectory:&isDirectory]) {
            continue;
        }
        if (isDirectory) {
            continue;
        }
        
        // Construct the extension of the item
        NSString* itemExtension = [item pathExtension];
        
        // Extension: png, jpg, jpeg
        if ([itemExtension caseInsensitiveCompare:@"png"]  == NSOrderedSame ||
            [itemExtension caseInsensitiveCompare:@"jpg"]  == NSOrderedSame ||
            [itemExtension caseInsensitiveCompare:@"jpeg"] == NSOrderedSame) {
            // Append the file to the pictures array
            [arrPictures addObject:item];
            
            // Continue
            continue;
        }
        
        // Extension: thumbnail
        if ([itemExtension caseInsensitiveCompare:@"thumbnail"] == NSOrderedSame) {
            // Check the thumbnail
            [self checkThumbnailByPath:itemPath];
            
            // Continue
            continue;
        }
    }
    
    // Construct the pictures list
    self.picturesList = [arrPictures copy];
}


#pragma mark - Data Retrieve

- (NSArray *) albums {
    // Refresh the albums list
    [self refreshAlbumsList];
    NSLog(@"[ INFO ] Refresh the albums list. (count: %lu)", [self.albumsList count]);
    
    // Return the albums list
    return self.albumsList;
}

- (NSArray *) pictures {
    // Refresh the pictures list
    [self refreshPicturesList];
    if (self.picturesList) {
        NSLog(@"[ INFO ] Refresh the pictures list succeeded. (album: \"%@\", count: %lu)", self.selectedAlbumName, self.picturesList.count);
    } else {
        NSLog(@"[ WARNING ] Refresh the pictures list failed. (album: \"%@\")", self.selectedAlbumName);
    }
    
    // Return the pictures list
    return self.picturesList;
}

- (UIImage *) pictureByFileName:(NSString *)fileName albumName:(NSString *)albumName {
    NSLog(@"[ INFO ] Fetch the picture data. (fileName: \"%@\", albumName: \"%@\")", fileName, albumName);
    
    // Construct the file path
    NSString* filePath = [[self.albumsDirectoryPath stringByAppendingPathComponent:albumName] stringByAppendingPathComponent:fileName];
    
    // Check the existence and item type of the path
    BOOL isDirectory;
    if (![[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDirectory]) {
        NSLog(@"[ WARNING ] The file does not exist. (filePath: \"%@\")", filePath);
        return nil;
    }
    if (isDirectory) {
        NSLog(@"[ WARNING ] The item is not a file. (filePath: \"%@\", isDirectory: %d)", filePath, isDirectory);
        return nil;
    }
    
    // Load the image data
    UIImage* image = [[UIImage alloc] initWithContentsOfFile:filePath];
    
    // Return the image data
    return image;
}

- (UIImage *) thumbnailByPictureFileName:(NSString*)fileName albumName:(NSString *)albumName {
    NSLog(@"[ INFO ] Fetch the thumbnail data of corresponding picture file. (fileName: \"%@\", albumName: \"%@\")", fileName, albumName);
#warning todo
    // Construct the file path
    NSString* filePath = [[self.albumsDirectoryPath stringByAppendingPathComponent:albumName] stringByAppendingPathComponent:fileName];
    NSString* thumbPath = [self thumbnailPathByFilename:fileName albumName:albumName];
    
    if (![[NSFileManager defaultManager] fileExistsAtPath:thumbPath]) {
        
        // Check the existence and item type of the path
        BOOL isDirectory;
        if (![[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDirectory]) {
            NSLog(@"[ WARNING ] The file does not exist. (filePath: \"%@\")", filePath);
            return nil;
        }
        if (isDirectory) {
            NSLog(@"[ WARNING ] The item is not a file. (filePath: \"%@\", isDirectory: %d)", filePath, isDirectory);
            return nil;
        }
        
        // Load the image data
        UIImage* image = [[UIImage alloc] initWithContentsOfFile:filePath];
        UIImage* thumb = [self downscaleImage:image targetSize:CGSizeMake(160, 120)];
        NSData* thumnFile = UIImagePNGRepresentation(thumb);
        [thumnFile writeToFile:thumbPath atomically:YES];
        return thumb;
    }else{
        UIImage* thumb = [UIImage imageWithContentsOfFile:thumbPath];
        return thumb;
    }
    
       // Return the image data
    return nil;
}

-(NSString*) thumbnailPathByFilename:(NSString*) fileName albumName:(NSString *)albumName{
    NSString* filePath = [[self.albumsDirectoryPath stringByAppendingPathComponent:albumName] stringByAppendingPathComponent:fileName];
    NSString* thumbPath = [filePath stringByAppendingPathExtension:@"thumbnail"];
    return thumbPath;
}

// >>> DEBUG
-(UIImage*) downscaleImage:(UIImage*)origin targetSize:(CGSize)targetSizes{
    if (!origin) {
        return nil;
    }
    
    UIGraphicsBeginImageContextWithOptions(targetSizes, NO, [UIScreen mainScreen].scale);
    [origin drawInRect:CGRectMake(0, 0, targetSizes.width, targetSizes.height)];
    UIImage* output = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return output;
}

#pragma mark - Operations

- (AlbumManagerCreateAlbumResult) createAlbumByName:(NSString *)name {
    NSError* error;
    
    // Refresh the albums list
    [self refreshAlbumsList];
    
    // Check if the album already exists
    for (NSUInteger i=0; i<[self.albumsList count]; ++i) {
        NSString* currentAlbumName = [self.albumsList objectAtIndex:i];
        if ([currentAlbumName isEqualToString:name]) {
            NSLog(@"[ WARNING ] Album already exists. (album: \"%@\")", name);
            return AlbumManagerCreateAlbumExisting;
        }
    }
    
    // Create the album
    NSLog(@"[ INFO ] Create new album. (album: \"%@\")", name);
    [[NSFileManager defaultManager] createDirectoryAtPath:([self.albumsDirectoryPath stringByAppendingPathComponent:name]) withIntermediateDirectories:YES attributes:nil error:&error];
    
    // Detect error
    if (error == nil) {
        return AlbumManagerCreateAlbumSucceeded;
    } else {
        return AlbumManagerCreateAlbumFailed;
    }
}

- (AlbumManagerDeleteAlbumResult) deleteAlbumByName:(NSString *)name {
    NSError* error;
    
    // Refresh the albums list
    [self refreshAlbumsList];
    
    // Check if the album exists
    BOOL doExists = NO;
    for (NSUInteger i=0; i<[self.albumsList count]; ++i) {
        NSString* currentAlbumName = [self.albumsList objectAtIndex:i];
        if ([currentAlbumName isEqualToString:name]) {
            doExists = YES;
        }
    }
    if (!doExists) {
        NSLog(@"[ WARNING ] Album does not exist. (album: \"%@\")", name);
        return AlbumManagerDeleteAlbumInexistent;
    }
    
    // Delete the album
    NSLog(@"[ INFO ] Delete an existing album. (album: \"%@\")", name);
    [[NSFileManager defaultManager] removeItemAtPath:[self.albumsDirectoryPath stringByAppendingPathComponent:name] error:&error];
    
    // Detect error
    if (error == nil) {
        return AlbumManagerDeleteAlbumSucceeded;
    } else {
        return AlbumManagerDeleteAlbumFailed;
    }
}


@end
